/**
 @file sys_tsingma_datapath.h

 @date 2017-12-28

 @version v2.0

 The file define APIs and types use in sys layer
*/
#ifndef _SYS_TMM_DATAPATH_H
#define _SYS_TMM_DATAPATH_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "sal.h"
#include "ctc_const.h"
#include "ctc_vector.h"
#include "sys_usw_dmps.h"
#include "sys_usw_common.h"
#include "sys_usw_datapath.h"
#include "sys_tmm_mac.h"

/***************************************************************
 *
 * Defines and Macros
 *
 ***************************************************************/
#define SYS_TMM_DP_NUM                          2
#define SYS_TMM_MAX_SERDES_NUM_PER_DP          48

#define SYS_TMM_MAX_SERDES_NUM                 (SYS_TMM_MAX_SERDES_NUM_PER_DP*SYS_TMM_DP_NUM)
#define SYS_TMM_MAX_MAC_NUM_PER_DP            160
#define SYS_TMM_MAX_MAC_NUM                   (SYS_TMM_MAX_MAC_NUM_PER_DP*2)
#define SYS_TMM_MAX_PCS_NUM_PER_DP             48
#define SYS_TMM_MAX_HSS_NUM_PER_DP             6
#define SYS_TMM_MAX_HSS_NUM                    (SYS_TMM_MAX_HSS_NUM_PER_DP*SYS_TMM_DP_NUM)
#define SYS_TMM_PCS_X8_LANE_NUM                8
#define SYS_TMM_PCS_X16_LANE_NUM               16

#define SYS_TMM_CHANNEL_NUM_PER_DP              128
#define SYS_TMM_LPORT_NUM_PER_DP              SYS_TMM_CHANNEL_NUM_PER_DP
#define SYS_TMM_CHANNEL_NUM                     (SYS_TMM_CHANNEL_NUM_PER_DP*SYS_TMM_DP_NUM)
#define SYS_TMM_LPORT_NUM                     (SYS_TMM_LPORT_NUM_PER_DP*SYS_TMM_DP_NUM)
#define SYS_TMM_NETWORK_CHANNEL_NUM_PER_DP 112
#define SYS_TMM_TXQM_NUM_PER_DP                 4
#define SYS_TMM_MISC_PORT_START                 242  /*the same value as SYS_DMPS_MISC_PORT_START*/
/* preserve the precision when operate division on integer.*/
#define SYS_SCALE_FACTOR                        1000 
#define SYS_TMM_MAX_BANDWIDTH_PER_TXQM          400  /*400G*/

#define SYS_TMM_DP_BW_MAX                        1700
#define SYS_TMM_CLK_DEFAULT                      1050

#define SYS_TMM_GET_SERDES_ID_BY_LANE(hss_id, lane) ((uint8)((hss_id) * SYS_TMM_LANE_NUM_PER_HSS + (lane)))

#define SYS_TMM_MAP_SERDES_TO_PHY_LANE_ID(serdes_id)    (serdes_id)
#define SYS_TMM_GET_DP_ID_FROM_SERDES(serdes_id) \
    ((96 > (serdes_id)) ? (SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id) / SYS_TMM_MAX_HSS_NUM_PER_DP) : (((serdes_id)-96)/2))
#define SYS_TMM_GET_DP_ID_FROM_HSSID(hss_id) ((hss_id) / SYS_TMM_MAX_HSS_NUM_PER_DP)
#define SYS_TMM_GET_DP_ID_FROM_MACID(mac_id) ((SYS_TMM_MAX_MAC_NUM <= (mac_id)) ? \
                                              (((mac_id) - SYS_TMM_MAX_MAC_NUM) / 2) : \
                                              ((mac_id) / SYS_TMM_MAX_MAC_NUM_PER_DP))
#define SYS_TMM_GET_DP_ID_FROM_CHANID(chan_id) ((chan_id) / SYS_TMM_CHANNEL_NUM_PER_DP)
#define SYS_TMM_GET_DP_ID_FROM_LPORT(lport)  ((lport)  / SYS_TMM_LPORT_NUM_PER_DP)
#define SYS_TMM_GET_MACID_PER_DP(mac_id) ((mac_id) % SYS_TMM_MAX_MAC_NUM_PER_DP)
#define SYS_TMM_GET_LPORT_PER_DP(lport) ((lport) % SYS_TMM_LPORT_NUM_PER_DP)
#define SYS_TMM_GET_CHANN_PER_DP(chan_id) ((chan_id) % SYS_TMM_CHANNEL_NUM_PER_DP)
#define SYS_TMM_GET_MACID_PER_TXQM(mac_id) ((mac_id) % SYS_TMM_MAX_MAC_NUM_PER_TXQM)

#define SYS_TMM_CPUMAC_SERDES_START_ID 96
#define SYS_TMM_CPUMAC_SERDES_NUM      4
#define SYS_TMM_CPUMAC_HSS_ID          12
#define SYS_TMM_CPUMAC_TXQM_ID         8
#define SYS_TMM_CPUMAC_GET_MAC_HW_IDX(mac_id) (((MISC_CHAN_ITEM_BUTT + SYS_TMM_MAX_MAC_NUM) > (mac_id)) ? \
                                                ((mac_id) - SYS_TMM_MAX_MAC_NUM) : \
                                                ((mac_id) - MISC_CHAN_ITEM_BUTT - SYS_TMM_MAX_MAC_NUM + 2));
#define SYS_TMM_MAX_CAL_LEN            512
#define SYS_TMM_SERDES_REF_CLK_FREQ    15625


#define SYS_TMM_IS_SERDES_SUPPORT_QSGMII(serdes_id)  \
    ((0 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id)) \
    || (2 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id)) \
    || (6 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id)) \
    || (8 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id)))

#define SYS_TMM_GET_TXQM_BY_SERDES(serdes_id, txqm_id) \
{\
    if ((0 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id))       \
        || (1 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id)))   \
        txqm_id = 0;                                           \
    else if ((2 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id))  \
        || (3 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id)))   \
        txqm_id = 1;                                           \
    else if (4 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id))   \
        txqm_id = 2;                                          \
    else if (5 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id))   \
        txqm_id = 3;                                          \
    else if ((6 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id))  \
        || (7 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id)))   \
        txqm_id = 4;                                           \
    else if ((8 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id))  \
        || (9 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id)))   \
        txqm_id = 5;                                           \
    else if (10 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id))  \
        txqm_id = 6;                                           \
    else if (11 == SYS_TMM_MAP_SERDES_TO_HSS_IDX(serdes_id))  \
        txqm_id = 7;                                           \
}

#define SYS_TMM_GET_TXQM_BY_MACID(mac_id) ((uint8)((mac_id) / SYS_TMM_MAX_MAC_NUM_PER_TXQM))
#define SYS_TMM_GET_TXQM_PER_DP(txqm_id) ((txqm_id) % SYS_TMM_TXQM_NUM_PER_DP)


#define SYS_TMM_IS_PCS_X16(txqm_id)  (((0 == (txqm_id)) || (1 == (txqm_id)) || (4 == (txqm_id)) || (5 == (txqm_id))) ? TRUE : FALSE)

#define SYS_TMM_GET_PCSXIDX(txqm_id, pcs_x8_x16_index)\
    do {\
        switch(txqm_id)\
        {\
            case 0:\
            case 2:\
                pcs_x8_x16_index = 0;\
                break;\
            case 1:\
            case 3:\
                pcs_x8_x16_index = 1;\
                break;\
            case 4:\
            case 6:\
                pcs_x8_x16_index = 2;\
                break;\
            case 5:\
            case 7:\
            default:\
                pcs_x8_x16_index = 3;\
                break;\
        }\
    } while(0)

#define SYS_TMM_GET_PCS_LANE_NUM(txqm_id) (SYS_TMM_IS_PCS_X16(txqm_id) ? SYS_TMM_PCS_X16_LANE_NUM : SYS_TMM_PCS_X8_LANE_NUM)

#define SYS_TMM_GET_PORT_IFMODE_WITH_MODE(mode, speed, iftype)  \
{\
    if (CTC_CHIP_SERDES_SGMII_MODE == (mode))          { speed = CTC_PORT_SPEED_1G;   iftype = CTC_PORT_IF_SGMII; } \
    else if (CTC_CHIP_SERDES_XFI_MODE == (mode))       { speed = CTC_PORT_SPEED_10G;  iftype = CTC_PORT_IF_XFI;   } \
    else if (CTC_CHIP_SERDES_QSGMII_MODE == (mode))    { speed = CTC_PORT_SPEED_1G;   iftype = CTC_PORT_IF_QSGMII;} \
    else if (CTC_CHIP_SERDES_2DOT5G_MODE == (mode))    { speed = CTC_PORT_SPEED_2G5;  iftype = CTC_PORT_IF_2500X; } \
    else if (CTC_CHIP_SERDES_XLG_MODE == (mode))       { speed = CTC_PORT_SPEED_40G;  iftype = CTC_PORT_IF_CR4;   } \
    else if (CTC_CHIP_SERDES_CG_MODE == (mode))        { speed = CTC_PORT_SPEED_100G; iftype = CTC_PORT_IF_CR4;   } \
    else if (CTC_CHIP_SERDES_XXVG_MODE == (mode))      { speed = CTC_PORT_SPEED_25G;  iftype = CTC_PORT_IF_CR;    } \
    else if (CTC_CHIP_SERDES_LG_MODE == (mode))        { speed = CTC_PORT_SPEED_50G;  iftype = CTC_PORT_IF_CR2;   } \
    else if (CTC_CHIP_SERDES_100BASEFX_MODE == (mode)) { speed = CTC_PORT_SPEED_100M; iftype = CTC_PORT_IF_FX;    } \
    else if (CTC_CHIP_SERDES_LG_R1_MODE == (mode))     { speed = CTC_PORT_SPEED_50G;  iftype = CTC_PORT_IF_CR;    } \
    else if (CTC_CHIP_SERDES_CG_R2_MODE == (mode))     { speed = CTC_PORT_SPEED_100G; iftype = CTC_PORT_IF_CR2;   } \
    else if (CTC_CHIP_SERDES_CCG_R4_MODE == (mode))    { speed = CTC_PORT_SPEED_200G; iftype = CTC_PORT_IF_CR4;   } \
    else if (CTC_CHIP_SERDES_CDG_R8_MODE == (mode))    { speed = CTC_PORT_SPEED_400G; iftype = CTC_PORT_IF_CR8;   } \
}

#define SYS_TMM_GET_PORT_SPEED(mode, speed)  \
{\
    if (CTC_CHIP_SERDES_SGMII_MODE == (mode))          { speed = CTC_PORT_SPEED_1G;  } \
    else if (CTC_CHIP_SERDES_XFI_MODE == (mode))       { speed = CTC_PORT_SPEED_10G; } \
    else if (CTC_CHIP_SERDES_QSGMII_MODE == (mode))    { speed = CTC_PORT_SPEED_1G;  } \
    else if (CTC_CHIP_SERDES_2DOT5G_MODE == (mode))    { speed = CTC_PORT_SPEED_2G5; } \
    else if (CTC_CHIP_SERDES_XLG_MODE == (mode))       { speed = CTC_PORT_SPEED_40G; } \
    else if (CTC_CHIP_SERDES_CG_MODE == (mode))        { speed = CTC_PORT_SPEED_100G;} \
    else if (CTC_CHIP_SERDES_XXVG_MODE == (mode))      { speed = CTC_PORT_SPEED_25G; } \
    else if (CTC_CHIP_SERDES_LG_MODE == (mode))        { speed = CTC_PORT_SPEED_50G; } \
    else if (CTC_CHIP_SERDES_100BASEFX_MODE == (mode)) { speed = CTC_PORT_SPEED_100M;} \
    else if (CTC_CHIP_SERDES_LG_R1_MODE == (mode))     { speed = CTC_PORT_SPEED_50G; } \
    else if (CTC_CHIP_SERDES_CG_R2_MODE == (mode))     { speed = CTC_PORT_SPEED_100G;} \
    else if (CTC_CHIP_SERDES_CCG_R4_MODE == (mode))    { speed = CTC_PORT_SPEED_200G;} \
    else if (CTC_CHIP_SERDES_CDG_R8_MODE == (mode))    { speed = CTC_PORT_SPEED_400G;} \
    else if (CTC_CHIP_SERDES_XLG_R2_MODE == (mode))    { speed = CTC_PORT_SPEED_40G;} \
    else                                             { speed = CTC_PORT_SPEED_MAX; } \
}

#define SYS_TMM_GET_PORT_IFTYPE(mode, iftype)  \
{\
    if (CTC_CHIP_SERDES_SGMII_MODE == (mode))          {iftype = CTC_PORT_IF_SGMII; } \
    else if (CTC_CHIP_SERDES_XFI_MODE == (mode))       {iftype = CTC_PORT_IF_XFI;   } \
    else if (CTC_CHIP_SERDES_QSGMII_MODE == (mode))    {iftype = CTC_PORT_IF_QSGMII;} \
    else if (CTC_CHIP_SERDES_2DOT5G_MODE == (mode))    {iftype = CTC_PORT_IF_2500X; } \
    else if (CTC_CHIP_SERDES_XLG_MODE == (mode))       {iftype = CTC_PORT_IF_CR4;   } \
    else if (CTC_CHIP_SERDES_CG_MODE == (mode))        {iftype = CTC_PORT_IF_CR4;   } \
    else if (CTC_CHIP_SERDES_XXVG_MODE == (mode))      {iftype = CTC_PORT_IF_CR;    } \
    else if (CTC_CHIP_SERDES_LG_MODE == (mode))        {iftype = CTC_PORT_IF_CR2;   } \
    else if (CTC_CHIP_SERDES_100BASEFX_MODE == (mode)) {iftype = CTC_PORT_IF_FX;    } \
    else if (CTC_CHIP_SERDES_LG_R1_MODE == (mode))     {iftype = CTC_PORT_IF_CR;    } \
    else if (CTC_CHIP_SERDES_CG_R2_MODE == (mode))     {iftype = CTC_PORT_IF_CR2;   } \
    else if (CTC_CHIP_SERDES_CCG_R4_MODE == (mode))    {iftype = CTC_PORT_IF_CR4;   } \
    else if (CTC_CHIP_SERDES_CDG_R8_MODE == (mode))    {iftype = CTC_PORT_IF_CR8;   } \
}


#define SYS_TMM_GET_SERDES_MODE_BY_IFMODE(speed, iftype, mode)  \
{\
    if ((CTC_PORT_SPEED_100M == (speed)) && (CTC_PORT_IF_FX == (iftype)))          mode = CTC_CHIP_SERDES_100BASEFX_MODE; \
    else if ((CTC_PORT_SPEED_1G == (speed)) && (CTC_PORT_IF_SGMII == (iftype)))    mode = CTC_CHIP_SERDES_SGMII_MODE;     \
    else if ((CTC_PORT_SPEED_1G == (speed)) && (CTC_PORT_IF_QSGMII == (iftype)))   mode = CTC_CHIP_SERDES_QSGMII_MODE;    \
    else if ((CTC_PORT_SPEED_10G == (speed)) && ((CTC_PORT_IF_XFI == (iftype)) || \
                                                (CTC_PORT_IF_CR == (iftype)) || \
                                                (CTC_PORT_IF_KR == (iftype))))     mode = CTC_CHIP_SERDES_XFI_MODE;       \
    else if ((CTC_PORT_SPEED_2G5 == (speed)) && (CTC_PORT_IF_2500X == (iftype)))   mode = CTC_CHIP_SERDES_2DOT5G_MODE;    \
    else if ((CTC_PORT_SPEED_40G == (speed)) && (CTC_PORT_IF_CR4 == (iftype)))     mode = CTC_CHIP_SERDES_XLG_MODE;       \
    else if ((CTC_PORT_SPEED_40G == (speed)) && (CTC_PORT_IF_KR4 == (iftype)))     mode = CTC_CHIP_SERDES_XLG_MODE;       \
    else if ((CTC_PORT_SPEED_100G == (speed)) && (CTC_PORT_IF_CR4 == (iftype)))    mode = CTC_CHIP_SERDES_CG_MODE;        \
    else if ((CTC_PORT_SPEED_100G == (speed)) && (CTC_PORT_IF_KR4 == (iftype)))    mode = CTC_CHIP_SERDES_CG_MODE;        \
    else if ((CTC_PORT_SPEED_100G == (speed)) && (CTC_PORT_IF_CR2 == (iftype)))    mode = CTC_CHIP_SERDES_CG_R2_MODE;     \
    else if ((CTC_PORT_SPEED_100G == (speed)) && (CTC_PORT_IF_KR2 == (iftype)))    mode = CTC_CHIP_SERDES_CG_R2_MODE;     \
    else if ((CTC_PORT_SPEED_25G == (speed)) && (CTC_PORT_IF_CR == (iftype)))      mode = CTC_CHIP_SERDES_XXVG_MODE;      \
    else if ((CTC_PORT_SPEED_25G == (speed)) && (CTC_PORT_IF_KR == (iftype)))      mode = CTC_CHIP_SERDES_XXVG_MODE;      \
    else if ((CTC_PORT_SPEED_50G == (speed)) && (CTC_PORT_IF_CR2 == (iftype)))     mode = CTC_CHIP_SERDES_LG_MODE;        \
    else if ((CTC_PORT_SPEED_50G == (speed)) && (CTC_PORT_IF_KR2 == (iftype)))     mode = CTC_CHIP_SERDES_LG_MODE;        \
    else if ((CTC_PORT_SPEED_50G == (speed)) && (CTC_PORT_IF_CR == (iftype)))      mode = CTC_CHIP_SERDES_LG_R1_MODE;     \
    else if ((CTC_PORT_SPEED_50G == (speed)) && (CTC_PORT_IF_KR == (iftype)))      mode = CTC_CHIP_SERDES_LG_R1_MODE;     \
    else if ((CTC_PORT_SPEED_200G == (speed)) && (CTC_PORT_IF_CR4 == (iftype)))    mode = CTC_CHIP_SERDES_CCG_R4_MODE;    \
    else if ((CTC_PORT_SPEED_200G == (speed)) && (CTC_PORT_IF_KR4 == (iftype)))    mode = CTC_CHIP_SERDES_CCG_R4_MODE;    \
    else if ((CTC_PORT_SPEED_400G == (speed)) && (CTC_PORT_IF_CR8 == (iftype)))    mode = CTC_CHIP_SERDES_CDG_R8_MODE;    \
    else if ((CTC_PORT_SPEED_400G == (speed)) && (CTC_PORT_IF_KR8 == (iftype)))    mode = CTC_CHIP_SERDES_CDG_R8_MODE;    \
    else if ((CTC_PORT_SPEED_40G == (speed)) && (CTC_PORT_IF_CR2 == (iftype)))     mode = CTC_CHIP_SERDES_XLG_R2_MODE;       \
    else if ((CTC_PORT_SPEED_40G == (speed)) && (CTC_PORT_IF_KR2 == (iftype)))     mode = CTC_CHIP_SERDES_XLG_R2_MODE;       \
    else                                                                       mode = CTC_CHIP_MAX_SERDES_MODE;       \
}

#define SYS_TMM_GET_LANE_NUM_BY_ITF_TYPE(interface_type, serdes_num) \
do {\
    switch(interface_type)\
    {\
        case CTC_PORT_IF_KR2:\
        case CTC_PORT_IF_CR2:\
            serdes_num = 2;\
            break;\
        case CTC_PORT_IF_KR4:\
        case CTC_PORT_IF_CR4:\
            serdes_num = 4;\
            break;\
        case CTC_PORT_IF_KR8:\
        case CTC_PORT_IF_CR8:\
            serdes_num = 8;\
            break;\
        default:\
            serdes_num = 1;\
            break;\
    }\
}while(0)

#define SYS_TMM_GET_LANE_NUM_BY_MODE(mode, lane_num) \
do {\
    switch(mode)\
    {\
        case CTC_CHIP_SERDES_LG_MODE:\
        case CTC_CHIP_SERDES_CG_R2_MODE:\
        case CTC_CHIP_SERDES_XLG_R2_MODE:\
            lane_num = 2;\
            break;\
        case CTC_CHIP_SERDES_XLG_MODE:\
        case CTC_CHIP_SERDES_CG_MODE:\
        case CTC_CHIP_SERDES_CCG_R4_MODE:\
            lane_num = 4;\
            break;\
        case CTC_CHIP_SERDES_CDG_R8_MODE:\
            lane_num = 8;\
            break;\
        case CTC_CHIP_SERDES_XFI_MODE:\
        case CTC_CHIP_SERDES_SGMII_MODE:\
        case CTC_CHIP_SERDES_QSGMII_MODE:\
        case CTC_CHIP_SERDES_2DOT5G_MODE:\
        case CTC_CHIP_SERDES_XXVG_MODE:\
        case CTC_CHIP_SERDES_LG_R1_MODE:\
        default:\
            lane_num = 1;\
            break;\
    }\
} while(0)

#define SYS_TMM_GET_LANE_NUM_BY_RATIO(ratio, lane_num) \
do {\
    switch(ratio)\
    {\
        case PORT_1_SERDES_2:\
        case PORT_1_SERDES_1_HSPAM4:\
            lane_num = 2;\
            break;\
        case PORT_1_SERDES_4:\
        case PORT_1_SERDES_2_HSPAM4:\
            lane_num = 4;\
            break;\
        case PORT_1_SERDES_8:\
            lane_num = 8;\
            break;\
        case PORT_0_SERDES_0:\
        case PORT_1_SERDES_1:\
        case PORT_4_SERDES_1:\
        default:\
            lane_num = 1;\
            break;\
    }\
} while(0)

#define SYS_TMM_GET_PORT_NUM_BY_MODE(mode, port_num) \
do {\
    switch(mode)\
    {\
        case CTC_CHIP_SERDES_QSGMII_MODE:\
            port_num = 4;\
            break;\
        case CTC_CHIP_SERDES_LG_MODE:\
        case CTC_CHIP_SERDES_CG_R2_MODE:\
        case CTC_CHIP_SERDES_XLG_MODE:\
        case CTC_CHIP_SERDES_CG_MODE:\
        case CTC_CHIP_SERDES_CCG_R4_MODE:\
        case CTC_CHIP_SERDES_CDG_R8_MODE:\
        case CTC_CHIP_SERDES_XFI_MODE:\
        case CTC_CHIP_SERDES_SGMII_MODE:\
        case CTC_CHIP_SERDES_2DOT5G_MODE:\
        case CTC_CHIP_SERDES_XXVG_MODE:\
        case CTC_CHIP_SERDES_LG_R1_MODE:\
            port_num = 1;\
            break;\
        default:\
            port_num = 0;\
            break;\
    }\
} while(0)

#define SYS_TMM_GET_CHAN_NUM_BY_MODE SYS_TMM_GET_PORT_NUM_BY_MODE
#define SYS_TMM_MODE_IS_PAM4(mode) ((CTC_CHIP_SERDES_LG_R1_MODE == (mode)) || (CTC_CHIP_SERDES_CG_R2_MODE == (mode)) || \
                                    (CTC_CHIP_SERDES_CCG_R4_MODE == (mode)) || (CTC_CHIP_SERDES_CDG_R8_MODE == (mode)))
#define SYS_TMM_GET_HSS_TYPE(hss_id, hss_type) do {\
    if((3 >= (hss_id)) || ((6 <= (hss_id)) && (9 >= (hss_id))))\
        hss_type = SYS_DATAPATH_HSS_TYPE_15G;\
    else if(((4 <= (hss_id)) && (5 >= (hss_id))) || ((10 <= (hss_id)) && (11 >= (hss_id))))\
        hss_type = SYS_DATAPATH_HSS_TYPE_28G;\
    else\
        hss_type = SYS_DATAPATH_HSS_TYPE_CPUMAC;\
} while(0)
#define SYS_TMM_GET_TXQM_ID_BY_HSS_ID(hss_id, txqm_id) do {\
    switch(hss_id)\
    {\
        case 0:\
        case 1:\
            txqm_id = 0;\
            break;\
        case 2:\
        case 3:\
            txqm_id = 1;\
            break;\
        case 4:\
            txqm_id = 2;\
            break;\
        case 5:\
            txqm_id = 3;\
            break;\
        case 6:\
        case 7:\
            txqm_id = 4;\
            break;\
        case 8:\
        case 9:\
            txqm_id = 5;\
            break;\
        case 10:\
            txqm_id = 6;\
            break;\
        case 11:\
        default:\
            txqm_id = 7;\
            break;\
    }\
}while(0)
#define SYS_TMM_JUDGE_PCSX16A(hss_id) (((0 == (hss_id)) || (2 == (hss_id)) || (6 == (hss_id)) || (8 == (hss_id))) ? TRUE : FALSE)
#define SYS_ERROR_RETURN_SET_LPORT2LSD(lport, lport2lsd, logic_serdes) do {\
    if(SYS_TMM_USELESS_ID8 != lport2lsd)\
    {\
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %d: illegal arrangement (%u %u) and (%u %u)\n",\
            __LINE__, logic_serdes, lport, lport2lsd, lport);\
        sal_printf(" %d: illegal arrangement (%u %u) and (%u %u)\n",\
            __LINE__, logic_serdes, lport, lport2lsd, lport);\
        return CTC_E_INVALID_PARAM;\
    }\
    lport2lsd = logic_serdes;\
}\
while(0)

/*
 Port : SerDes:
 #1, 1:1
 #2, 1:2
 #3, 1:4
 #4, 1:8
 #5, 4:1
 */
enum _tmm_port_serdes_ratio_e
{
    PORT_0_SERDES_0,
    PORT_1_SERDES_1,
    PORT_1_SERDES_2,
    PORT_1_SERDES_4,
    PORT_1_SERDES_8,
    PORT_4_SERDES_1,
    PORT_1_SERDES_1_HSPAM4,
    PORT_1_SERDES_2_HSPAM4,
    PORT_SERDES_RATIO_BUTT,
};
typedef enum _tmm_port_serdes_ratio_e _tmm_port_serdes_ratio_t;

enum _tmm_dyn_switch_quad_action_e
{
    L0_P0S0, /*lane 0 switch to PORT_0_SERDES_0*/
    L1_P0S0, /*lane 1 switch to PORT_0_SERDES_0*/
    L2_P0S0, /*lane 2 switch to PORT_0_SERDES_0*/
    L3_P0S0, /*lane 3 switch to PORT_0_SERDES_0*/
    L0_P1S1, /*lane 0 switch to PORT_1_SERDES_1*/
    L1_P1S1, /*lane 1 switch to PORT_1_SERDES_1*/
    L2_P1S1, /*lane 2 switch to PORT_1_SERDES_1*/
    L3_P1S1, /*lane 3 switch to PORT_1_SERDES_1*/
    L0_P1S2, /*lane 0 switch to PORT_1_SERDES_2*/
    L1_P1S2, /*lane 1 switch to PORT_1_SERDES_2*/
    L2_P1S2, /*lane 2 switch to PORT_1_SERDES_2*/
    L3_P1S2, /*lane 3 switch to PORT_1_SERDES_2*/
    L0_P1S4, /*lane 0 switch to PORT_1_SERDES_4*/
    L1_P1S4, /*lane 1 switch to PORT_1_SERDES_4*/
    L2_P1S4, /*lane 2 switch to PORT_1_SERDES_4*/
    L3_P1S4, /*lane 3 switch to PORT_1_SERDES_4*/
    L0_P4S1, /*lane 0 switch to PORT_4_SERDES_1*/
    L1_P4S1, /*lane 1 switch to PORT_4_SERDES_1*/
    L2_P4S1, /*lane 2 switch to PORT_4_SERDES_1*/
    L3_P4S1, /*lane 3 switch to PORT_4_SERDES_1*/
    L0_P1S1_HP, /*lane 0 switch to PORT_1_SERDES_1_HSPAM4*/
    L1_P1S1_HP, /*lane 1 switch to PORT_1_SERDES_1_HSPAM4*/
    L2_P1S1_HP, /*lane 2 switch to PORT_1_SERDES_1_HSPAM4*/
    L3_P1S1_HP, /*lane 3 switch to PORT_1_SERDES_1_HSPAM4*/
    L0_P1S2_HP, /*lane 0 switch to PORT_1_SERDES_2_HSPAM4*/
    L1_P1S2_HP, /*lane 1 switch to PORT_1_SERDES_2_HSPAM4*/
    L2_P1S2_HP, /*lane 2 switch to PORT_1_SERDES_2_HSPAM4*/
    L3_P1S2_HP, /*lane 3 switch to PORT_1_SERDES_2_HSPAM4*/
    QUAD_DS_ACTION_BUTT,
};
typedef enum _tmm_dyn_switch_quad_action_e _tmm_dyn_switch_quad_action_t;

enum _tmm_serdes_isdyn_flag_e
{
    TMM_SERDES_DYN_FORBID_ALL,  //cannot do dynamic switch
    TMM_SERDES_DYN_FORBID_QI,  //cannot switch to QSGMII, but allow other supported mode
    TMM_SERDES_DYN_ALLOW_ALL,  //allow switch to all supported mode
    TMM_SERDES_DYN_BUTT,
};
typedef enum _tmm_serdes_isdyn_flag_e _tmm_serdes_isdyn_flag_t;

#define SYS_TMM_GET_PORT_SERDES_RATIO(iftype, ratio) \
{ \
    if ((CTC_PORT_IF_FX == (iftype)) || (CTC_PORT_IF_SGMII == (iftype))     \
        || (CTC_PORT_IF_2500X == (iftype)) || (CTC_PORT_IF_XFI == (iftype)) \
        || (CTC_PORT_IF_KR == (iftype)) || (CTC_PORT_IF_CR == (iftype)))    \
        ratio = PORT_1_SERDES_1;                                   \
    else if ((CTC_PORT_IF_KR2 == (iftype)) || (CTC_PORT_IF_CR2 == (iftype)))\
        ratio = PORT_1_SERDES_2;                                   \
    else if ((CTC_PORT_IF_KR4 == (iftype)) || (CTC_PORT_IF_CR4 == (iftype)))\
        ratio = PORT_1_SERDES_4;                                   \
    else if ((CTC_PORT_IF_KR8 == (iftype)) || (CTC_PORT_IF_CR8 == (iftype)))\
        ratio = PORT_1_SERDES_8;                                   \
    else if (CTC_PORT_IF_QSGMII == (iftype))                              \
        ratio = PORT_4_SERDES_1;                                   \
}

#define SYS_TMM_GET_PORT_SERDES_RATIO_BY_MODE(mode, ratio) do\
{\
    switch(mode)\
    {\
        case CTC_CHIP_SERDES_QSGMII_MODE:\
            ratio = PORT_4_SERDES_1;\
            break;\
        case CTC_CHIP_SERDES_XFI_MODE:\
        case CTC_CHIP_SERDES_SGMII_MODE:\
        case CTC_CHIP_SERDES_2DOT5G_MODE:\
        case CTC_CHIP_SERDES_XXVG_MODE:\
            ratio = PORT_1_SERDES_1;\
            break;\
        case CTC_CHIP_SERDES_LG_MODE:\
            ratio = PORT_1_SERDES_2;\
            break;\
        case CTC_CHIP_SERDES_XLG_MODE:\
        case CTC_CHIP_SERDES_CG_MODE:\
        case CTC_CHIP_SERDES_CCG_R4_MODE:\
            ratio = PORT_1_SERDES_4;\
            break;\
        case CTC_CHIP_SERDES_CDG_R8_MODE:\
            ratio = PORT_1_SERDES_8;\
            break;\
        case CTC_CHIP_SERDES_LG_R1_MODE:\
            ratio = PORT_1_SERDES_1;\
            break;\
        case CTC_CHIP_SERDES_CG_R2_MODE:\
            ratio = PORT_1_SERDES_2;\
            break;\
        default: \
            ratio = PORT_0_SERDES_0;\
            break;\
    }\
}while(0)

#define SYS_TMM_IS_MAC_SUPPORT_QSGMII(mac_id)  \
    (((mac_id) <= 31)                            \
    || (((mac_id) >= 40) && ((mac_id) <= 71))      \
    || (((mac_id) >= 160) && ((mac_id) <= 191))    \
    || (((mac_id) >= 200) && ((mac_id) <= 231)))

#define SYS_TMM_IS_LOGICAL_SERDES_SUPPORT_QSGMII(logicaL_serdes_id)  \
    (((logicaL_serdes_id) <= 7)                            \
    || (((logicaL_serdes_id) >= 16) && ((logicaL_serdes_id) <= 23))      \
    || (((logicaL_serdes_id) >= 48) && ((logicaL_serdes_id) <= 55))    \
    || (((logicaL_serdes_id) >= 64) && ((logicaL_serdes_id) <= 71)))

#define SYS_TMM_USELESS_ID8   0xff
#define SYS_TMM_USELESS_ID16  0xffff
#define SYS_TMM_USELESS_ID32  0xffffffff

#define SYS_TMM_HSS_SUPPORT_QSGMII(hss_id) ((0 == (hss_id)) || (2 == (hss_id)) || (6 == (hss_id)) || (8 == (hss_id)))
#define SYS_GET_CHANNEL_BY_DP_CHANID(dp_chan_id, dp_id) ((dp_chan_id) + (dp_id)*SYS_TMM_CHANNEL_NUM_PER_DP)
#define SYS_CPUMAC_GET_CAL_MAC_ID(soft_mac_id, cal_mac_id) do {\
    switch(soft_mac_id)\
    {\
        case 320:\
            cal_mac_id = 160;\
            break;\
        case 321:\
            cal_mac_id = 161;\
            break;\
        case 322:\
            cal_mac_id = 322;\
            break;\
        case 323:\
        default:\
            cal_mac_id = 323;\
            break;\
    }\
}while(0)
#define SYS_TMM_IS_MISC_CHAN(dp, dp_chan) (((112 <= (dp_chan)) && (127 >= (dp_chan))) || \
                                           (MCHIP_CAP(SYS_CAP_CHANID_DROP) == SYS_GET_CHANNEL_BY_DP_CHANID(dp_chan, dp)))

#define SYS_TMM_GET_CTCXS_ID_BY_HSS_ID(hss_id, ctcxs_id, is_ctchs) \
{                                      \
    if ((0 == (hss_id)) || (1 == (hss_id)))       \
    {                                  \
        ctcxs_id = 0;                  \
        is_ctchs = 1;                  \
    }                                  \
    else if((2 == (hss_id)) || (3 == (hss_id))) \
    {                                  \
        ctcxs_id = 1;                  \
        is_ctchs = 1;                  \
    }                                  \
    else if(4 == (hss_id))               \
    {                                  \
        ctcxs_id = 0;                  \
        is_ctchs = 0;                  \
    }                                  \
    else if(5 == (hss_id))               \
    {                                  \
        ctcxs_id = 1;                  \
        is_ctchs = 0;                  \
    }                                  \
    else if ((6 == (hss_id)) || (7 == (hss_id))) \
    {                                  \
        ctcxs_id = 2;                  \
        is_ctchs = 1;                  \
    }                                  \
    else if((8 == (hss_id)) || (9 == (hss_id))) \
    {                                  \
        ctcxs_id = 3;                  \
        is_ctchs = 1;                  \
    }                                  \
    else if(10 == (hss_id))              \
    {                                  \
        ctcxs_id = 2;                  \
        is_ctchs = 0;                  \
    }                                  \
    else if(11 == (hss_id))              \
    {                                  \
        ctcxs_id = 3;                  \
        is_ctchs = 0;                  \
    }                                  \
}

struct sys_logic_lane_to_pcs_mac_map_s
{
    uint8  pcs_idx;
    uint16 mac_id;
    uint8  pcs_l_id;
};
typedef struct sys_logic_lane_to_pcs_mac_map_s sys_logic_lane_to_pcs_mac_map_t;

typedef struct {
    uint8  lport_num;
    uint16 lport[SYS_DATAPATH_DS_MAX_SERDES_NUM];
    uint8  upt_flag[SYS_DATAPATH_DS_MAX_SERDES_NUM];  /* sys_ds_mac_add_drop_flag_t */
}sys_datapath_dynamic_switch_lport_list_t;


enum sys_aps_type_e
{
    APS_TYEE_DISABLE = 0,
    APS_TYEE_MASTER,
    APS_TYEE_SLAVE,
};
typedef enum sys_aps_type_e sys_aps_type_t;

struct sys_aps_info_collect_s
{
    uint8 aps_type;            /* sys_aps_type_t */
    uint8 brother_mac_id;      /* brother(master or slave)'s txqm_mac_id */
};
typedef struct sys_aps_info_collect_s sys_aps_info_collect_t;

struct sys_nettx_cal_heap_s
{
    uint32 portid_order[SYS_TMM_MAX_MAC_NUM_PER_TXQM];/*interval,per port*/
    uint32 num[SYS_TMM_MAX_MAC_NUM_PER_TXQM];/*select num ,per port*/
    uint32 first_cal_record[SYS_TMM_MAX_MAC_NUM_PER_TXQM];/*record the index first select*/
    uint32 cnt_history[SYS_TMM_MAX_MAC_NUM_PER_TXQM];
    uint32 expect_margine[SYS_TMM_MAX_MAC_NUM_PER_TXQM+1];
};
typedef struct sys_nettx_cal_heap_s sys_nettx_cal_heap_t;

enum sys_dmps_misc_info_type_e
{
    MISC_INFO_TYPE_LPORT = 0,
    MISC_INFO_TYPE_CHAN_ID,
    MISC_INFO_TYPE_MAC_ID,
    MISC_INFO_TYPE_PORT_TYPE,
    MISC_INFO_TYPE_SPEED,
    MISC_INFO_TYPE_BUTT,
};
typedef enum sys_dmps_misc_info_type_e sys_dmps_misc_info_type_t;

enum sys_dmps_misc_info_item_e
{
    MISC_CHAN_CPU_MAC_0 = 0,
    MISC_CHAN_CPU_MAC_1,
    MISC_CHAN_LOO_0,
    MISC_CHAN_LOO_1,
    MISC_CHAN_LOO_2,
    MISC_CHAN_LOO_3,
    MISC_CHAN_OAM,
    MISC_CHAN_DMA_0,
    MISC_CHAN_DMA_1,
    MISC_CHAN_DMA_2,
    MISC_CHAN_DMA_3,
    MISC_CHAN_ITEM_BUTT,
};
typedef enum sys_dmps_misc_info_item_e sys_dmps_misc_info_item_t;

enum sys_chan_lport_occupy_flag_e
{
    SYS_CHAN_LPORT_OCCUPY_RSV,
    SYS_CHAN_LPORT_OCCUPY_IN_USE,
    SYS_CHAN_LPORT_OCCUPY_FREE,
    SYS_CHAN_LPORT_OCCUPY_BUTT,
};
typedef enum sys_chan_lport_occupy_flag_e sys_chan_lport_occupy_flag_t;

enum sys_resource_manage_using_stat_e
{
    SYS_RESOURCE_FREE,
    SYS_RESOURCE_IN_USE,
    SYS_RESOURCE_BUTT,
};
typedef enum sys_resource_manage_using_stat_e sys_resource_manage_using_stat_t;

enum sys_ds_lport_upt_flag_e
{
    SYS_DS_LPORT_REMAIN,
    SYS_DS_LPORT_ADD,
    SYS_DS_LPORT_DROP,
    SYS_DS_LPORT_BUTT,
};
typedef enum sys_ds_lport_upt_flag_e sys_ds_lport_upt_flag_t;

enum sys_ds_lport_force_upt_flag_e
{
    SYS_DS_LPORT_NO_FORCE_UPT,
    SYS_DS_LPORT_FORCE_UPT,
    SYS_DS_LPORT_FORCE_UPT_BUTT,
};
typedef enum sys_ds_lport_force_upt_flag_e sys_ds_lport_force_upt_flag_t;

enum sys_ds_lport_serdes_old_new_e
{
    SYS_DS_LPORT_SERDES_OLD,
    SYS_DS_LPORT_SERDES_NEW,
};
typedef enum sys_ds_lport_serdes_old_new_e sys_ds_lport_serdes_old_new_t;

enum sys_resource_arrange_type_e
{
    SYS_ARRANGE_NETWORK_PORT_BMP,   //network port (lport & channel & mac)
    SYS_ARRANGE_FLEXE_PORT_BMP,     //flexe (lport & channel & mac)
    SYS_ARRANGE_XPIPE_PMAC_BMP,     //x-pipe pmac channel (channel & mac)
    SYS_ARRANGE_MISC_CHAN_BMP,      //misc channel (lport & channel & mac)
    SYS_ARRANGE_EXT_PORT_BMP,       //ext-port (lport)
    SYS_ARRANGE_BMP_BUTT,
};
typedef enum sys_resource_arrange_type_e sys_resource_arrange_type_t;


enum sys_tmm_calendar_type_e
{
    SYS_TMM_GENERAL_CAL,
    SYS_TMM_NETTX_CAL,
    SYS_TMM_MAC_CAL,
    SYS_TMM_MAC_FIXLEN_CAL,
    SYS_TMM_FLEXE_MAC_CAL,
    SYS_TMM_SKIP_XPIPE_CAL,
    SYS_TMM_CAL_BUTT,
};
typedef enum sys_tmm_calendar_type_e sys_tmm_calendar_type_t;

#define SYS_BMP_TO_VAL_U8(bitmap) ((uint8)(0x1 << bitmap))
#define SYS_BMP_IS_SET(value, bmp_mask) ((bmp_mask) == ((value) & (bmp_mask)))
/***************************************************************
 *
 * Function declaration
 *
 ***************************************************************/
extern int32
sys_tmm_datapath_init_build_serdes_info(uint8 lchip, ctc_datapath_serdes_prop_t* p_serdes_raw);

extern int32
sys_tmm_datapath_init(uint8 lchip, ctc_datapath_global_cfg_t* p_datapath_cfg);

int32 sys_tmm_datapath_get_port_attr(uint8 lchip, uint16 lport, sys_datapath_lport_attr_t** port_attr);

int32 _sys_tmm_datapath_alloc_lport(uint8 lchip, uint8 logic_serdes_id, uint16* p_chan_id, uint16* p_lport, uint8 is_quad);

int32 _sys_tmm_ds_soft_table_upt(uint8 lchip, sys_tmm_ds_target_attr_t* p_ds_attr);

int32 sys_tmm_serdes_set_mode(uint8 lchip, ctc_chip_serdes_info_t* p_serdes_info);

extern int32
sys_tmm_datapath_get_idle_chanid(uint8 lchip, uint8 arrange_type, uint8 dp_id, uint8* p_chan_id);

extern int32
sys_tmm_datapath_get_idle_macid(uint8 lchip, uint8 arrange_type, uint8 txqm_id, uint16* p_mac_id);
    
extern int32
sys_tmm_datapath_get_idle_lport(uint8 lchip, uint8 arrange_type, uint16* p_lport);

extern int32
_sys_tmm_datapath_xpipe_resource_alloc(uint8 lchip, sys_datapath_lport_attr_t* port_attr);

extern int32
_sys_tmm_datapath_bufretrv_get_credit(uint8 lchip, uint8 speed_mode, sys_datapath_bufsz_step_t *step);

extern uint32
 _sys_tmm_datapath_epe_speed_to_credit(uint16 speed);

extern uint32
_sys_tmm_nettx_speed_to_credit(uint16 speed);

extern int32
_sys_tmm_datapath_get_internal_chan_start(uint8 lchip, uint8 dp_id, uint16* p_chan_id);

#ifdef __cplusplus
}
#endif

#endif

